/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright (c) 2008-2009, The KiWi Project (http://www.kiwi-project.eu)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * - Redistributions of source code must retain the above copyright notice, 
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, 
 *   this list of conditions and the following disclaimer in the documentation 
 *   and/or other materials provided with the distribution.
 * - Neither the name of the KiWi Project nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Contributor(s):
 * 
 * 
 */
package kiwi.core.model.rdf;

import kiwi.core.model.Constants;
import kiwi.core.model.content.MediaContent;
import kiwi.core.model.user.KiWiUser;
import kiwi.core.util.MD5;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Type;

import javax.persistence.*;
import java.io.*;

/**
 * MediaContent is a certain type of content for pictures, videos 
 * and other media data. The data itself is stored in a byte array.
 * Furthremore it contains the mime-type of the data and a file name.
 *
 * @author Sebastian Schaffert
 */
@Entity
@DiscriminatorValue("MEDIACONTENT")
@SecondaryTable( name = "MEDIACONTENT")
@AccessType("property")
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@org.hibernate.annotations.Table(appliesTo="MEDIACONTENT", optional=true)
public class KiWiMediaContentLiteral extends KiWiLiteral implements Serializable {

	private static final long serialVersionUID = -5020666543607571411L;

    private byte[] data;
    
    private String mimeType;

    // transient, used for caching purposes only
    private MediaContent mediaContent;


    public KiWiMediaContentLiteral() {
        super();
    }

    /**
     * Default Constructor
     */
    public KiWiMediaContentLiteral(KiWiUser author) {
    	super(author);
    }

    public KiWiMediaContentLiteral(MediaContent content) {
        super();
        setMediaContent(content);
    }


    public void setMediaContent(MediaContent content) {
        setData(content.getData());
        setMimeType(content.getMimeType());
    }

    @Transient
    public MediaContent getMediaContent() {

        if(mediaContent == null) {
            mediaContent = new MediaContent(getData(),getMimeType());
        }

        return mediaContent;
    }

    /**
     * Return the content of the literal, using the parametrized Java type
     *
     * @return
     */
    @Override
    public String getContent() {
        return new String(getData());
    }

    /**
     * Set the content of the literal to the content provided as parameter.
     *
     * @param content
     */
    @Override
    public void setContent(String content) {
        setData(content.getBytes());
    }

    /**
     * Get the data of this media content object as a byte array.
     * @return
     */
    @Lob
	@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType") //to fix postgres 'bug'
    @Basic(fetch=FetchType.LAZY)
    @Column(table = "MEDIACONTENT")
    public byte[] getData() {
        return data;
    }

    /**
     * Set the data of this media content object as a byte array.
     * @param data
     */
    public void setData(byte[] data) {
        this.data = data;
        setContentMd5(MD5.md5sum(data));
        if(mediaContent != null) {
            mediaContent.setData(data);
        }
    }

    /**
     * Get the data of this media content object as an input stream.
     * 
     * Currently just wraps the byte array in a ByteArrayInputStream, but more
     * efficient implementations could directly refer to the database instead.
     * @return
     */
    @Transient
    public InputStream getDataInputStream() {
        return new ByteArrayInputStream(getData());
    }

    /**
     * Get an output stream that allows to write data into this media content object.
     * 
     * Currently wraps the byte array in a ByteArrayOutputStream that is saved back to the
     * object when .close() is called.
     * @return
     */
    @Transient
    public OutputStream getDataOutputStream() {
        return new ByteArrayOutputStream() {
            @Override
            public void close() throws IOException {
                super.close();
                setData(this.toByteArray());
            }
            
        };
    }
    
    /**
     * Return the mime type of the media content contained in this object, e.g. image/jpeg.
     * 
     * This information is necessary for properly deciding how to render the content.
     * 
     * @return
     */
    @Basic
    @Column(table = "MEDIACONTENT")
    public String getMimeType() {
        return mimeType;
    }

    /**
     * Set the mime type of the media content contained in this object.
     * @param mimeType
     */
    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
        if(mediaContent != null) {
            mediaContent.setMimeType(mimeType);
        }
        setType(getRDFType(mimeType));
    }
    
    private final static String getRDFType(String mime_type) {
        String iw_type = "MultimediaObject";
        if (mime_type.startsWith("image")) {
            iw_type = "Image";
        } else if (mime_type.startsWith("video/flash")) {
            iw_type = "FlashVideo";
        } else if (mime_type.startsWith("video")) {
            iw_type = "Video";
        } else if (mime_type.startsWith("application/pdf")) {
            iw_type = "PDFDocument";
        } else if (mime_type.startsWith("application/msword")) {
            iw_type = "MSWordDocument";
        } else if (mime_type
                .startsWith("application/vnd.oasis.opendocument")
                || mime_type.startsWith("application/postscript")
                || mime_type.startsWith("application/vnd.ms-")) {
            iw_type = "Document";
        } else if (mime_type.startsWith("audio/mpeg")
                || mime_type.startsWith("audio/mp3")) {
            iw_type = "MP3Audio";
        } else if (mime_type.startsWith("audio")) {
            iw_type = "Audio";
        } else if (mime_type.startsWith("text/html")) {
            iw_type = "HTML";
        } else if (mime_type.startsWith("text")) {
            iw_type = "TEXT";
        }
        return Constants.NS_KIWI_CORE + iw_type;
    }
}
